<!DOCTYPE html>



  


<html class="theme-next mist use-motion" lang="zh-Hans">
<head><meta name="generator" content="Hexo 3.9.0">
  <meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="theme-color" content="#222">









<meta http-equiv="Cache-Control" content="no-transform">
<meta http-equiv="Cache-Control" content="no-siteapp">
















  
  
  <link href="/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css">







<link href="/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css">

<link href="/css/main.css?v=5.1.4" rel="stylesheet" type="text/css">


  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon32.ico?v=5.1.4">


  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon16.ico?v=5.1.4">


  <link rel="mask-icon" href="/images/logo.svg?v=5.1.4" color="#222">





  <meta name="keywords" content="multithreading,">










<meta name="description" content="介绍用于mutal exclusion的几个概念，并介绍几种implementation。最后列一下C++11多线程支持库，并举一个线程池的例子。">
<meta name="keywords" content="multithreading">
<meta property="og:type" content="article">
<meta property="og:title" content="mutex, criticalsection, semaphore">
<meta property="og:url" content="http://htelepathh.gitee.io/2021/04/17/mutex-criticalsection-semaphore/index.html">
<meta property="og:site_name" content="OUTPUT">
<meta property="og:description" content="介绍用于mutal exclusion的几个概念，并介绍几种implementation。最后列一下C++11多线程支持库，并举一个线程池的例子。">
<meta property="og:locale" content="zh-Hans">
<meta property="og:updated_time" content="2021-10-26T07:54:16.292Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="mutex, criticalsection, semaphore">
<meta name="twitter:description" content="介绍用于mutal exclusion的几个概念，并介绍几种implementation。最后列一下C++11多线程支持库，并举一个线程池的例子。">



<script type="text/javascript" id="hexo.configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/',
    scheme: 'Mist',
    version: '5.1.4',
    sidebar: {"position":"left","display":"post","offset":12,"b2t":false,"scrollpercent":false,"onmobile":true},
    fancybox: true,
    tabs: true,
    motion: {"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},
    duoshuo: {
      userId: '0',
      author: '博主'
    },
    algolia: {
      applicationID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    }
  };
</script>



  <link rel="canonical" href="http://htelepathh.gitee.io/2021/04/17/mutex-criticalsection-semaphore/">





  <title>mutex, criticalsection, semaphore | OUTPUT</title>
  








</head>

<body itemscope itemtype="http://schema.org/WebPage" lang="zh-Hans">

  
  
    
  

  <div class="container sidebar-position-left page-post-detail">
    <div class="headband"></div>

    <header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-wrapper">
  <div class="site-meta ">
    

    <div class="custom-logo-site-title">
      <a href="/" class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">OUTPUT</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
      
        <p class="site-subtitle">HTelepathH's blog</p>
      
  </div>

  <div class="site-nav-toggle">
    <button>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
    </button>
  </div>
</div>

<nav class="site-nav">
  

  
    <ul id="menu" class="menu">
      
        
        <li class="menu-item menu-item-home">
          <a href="/" rel="section">
            
            首页
          </a>
        </li>
      
        
        <li class="menu-item menu-item-categories">
          <a href="/categories" rel="section">
            
            分类
          </a>
        </li>
      
        
        <li class="menu-item menu-item-tags">
          <a href="/tags" rel="section">
            
            标签
          </a>
        </li>
      
        
        <li class="menu-item menu-item-archives">
          <a href="/archives" rel="section">
            
            归档
          </a>
        </li>
      
        
        <li class="menu-item menu-item-message">
          <a href="/message" rel="section">
            
            留言
          </a>
        </li>
      
        
        <li class="menu-item menu-item-about">
          <a href="/about" rel="section">
            
            关于
          </a>
        </li>
      

      
    </ul>
  

  
</nav>



 </div>
    </header>

    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          <div id="content" class="content">
            

  <div id="posts" class="posts-expand">
    

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="http://htelepathh.gitee.io/2021/04/17/mutex-criticalsection-semaphore/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="HTelepathH">
      <meta itemprop="description" content>
      <meta itemprop="image" content="/images/MOB.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="OUTPUT">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">mutex, criticalsection, semaphore</h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              
              <time title="创建于" itemprop="dateCreated datePublished" datetime="2021-04-17T16:09:01+08:00">
                2021-04-17
              </time>
            

            

            
          </span>

          
            <span class="post-category">
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">分类于</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/fundamental/" itemprop="url" rel="index">
                    <span itemprop="name">fundamental</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        <p>介绍用于<code>mutal exclusion</code>的几个概念，并介绍几种implementation。最后列一下C++11多线程支持库，并举一个线程池的例子。<br><a id="more"></a></p>
<h2 id="Comcepts"><a href="#Comcepts" class="headerlink" title="Comcepts"></a>Comcepts</h2><h3 id="mutex"><a href="#mutex" class="headerlink" title="mutex"></a>mutex</h3><p>就是lock，用于mutual exclusion。mutex一般是系统调用。<br>ps: 语言层面的<code>eastl::mutex</code>使用系统的critical section API，API中使用系统内核的mutex。</p>
<h3 id="critical-section"><a href="#critical-section" class="headerlink" title="critical section"></a>critical section</h3><p>临界区一般由mutex控制，在进入代码段前lock并在执行完后unlock。</p>
<h3 id="semaphore"><a href="#semaphore" class="headerlink" title="semaphore"></a>semaphore</h3><p>信号量简单的理解就是有counter的mutex，同样也是系统调用。是一个共享的int变量<code>s</code>，值非负。只能通过<code>wait(s)</code>和<code>signal(s)</code>访问。</p>
<ul>
<li><strong>P</strong> <code>wait(s)</code> decrements <code>s</code> if <code>s</code> &gt; 0; if not, the process is suspended.</li>
<li><strong>V</strong> <code>signal(s)</code> increments <code>s</code>. <code>wait(s)</code> and <code>signal(s)</code> are done atomically.</li>
</ul>
<h4 id="生产者消费者问题"><a href="#生产者消费者问题" class="headerlink" title="生产者消费者问题"></a>生产者消费者问题</h4><p>生产者生产对象给消费者，使用一个最大容量为<code>N</code>的队列通信。</p>
<ul>
<li>队列为空，消费者必须等待生产者生产</li>
<li>队列为满，生产者必须等待消费者消费<br>用三个信号量解决这个问题：</li>
<li><code>emptyCount</code> ：队列中的空余容量</li>
<li><code>fullCount</code> : 队列中已用容量</li>
<li><code>useQueue</code> : 控制队列的访问（可用mutex）</li>
</ul>
<p>初始值<code>emptyCount = N</code>，<code>fullCount = 0</code>，<code>useQueue = 1</code>.<br><figure class="highlight cpp"><table><tr><td class="code"><pre><span class="line"><span class="comment">//producer:</span></span><br><span class="line">P(emptyCount);</span><br><span class="line">P(useQueue);</span><br><span class="line">putItemIntoQueue(item);</span><br><span class="line">V(useQueue);</span><br><span class="line">V(fullCount);</span><br><span class="line"></span><br><span class="line"><span class="comment">//consumer:</span></span><br><span class="line">P(fullCount);</span><br><span class="line">P(useQueue);</span><br><span class="line">Item = getItemFromQueue();</span><br><span class="line">V(useQueue);</span><br><span class="line">V(emptyCount);</span><br></pre></td></tr></table></figure></p>
<p><code>emptyCount</code>可能小于实际空余容量，<code>fullCount</code>可能小于实际使用容量。<br><code>emptyCount + fullCount &lt;= N</code>永远成立。</p>
<h3 id="non-blocking-lock-free-wait-free"><a href="#non-blocking-lock-free-wait-free" class="headerlink" title="non-blocking, lock-free,  wait-free"></a>non-blocking, lock-free,  wait-free</h3><ul>
<li>non-blocking : 任何线程的suspension不会导致其他线程的failure或者suspension。</li>
<li>lock-free : guaranteed system-wide progress(no starvation)</li>
<li>wait-free : guaranteed per-thread progress</li>
</ul>
<h2 id="Implementation"><a href="#Implementation" class="headerlink" title="Implementation"></a>Implementation</h2><h3 id="test-and-set"><a href="#test-and-set" class="headerlink" title="test-and-set"></a>test-and-set</h3><p><code>test-and-set-lock(TSL)</code>可以由双端口存储器硬件实现，也可以由指令集在软件层面实现。<br><code>test-and-set</code>指令：对一个内存位置写入1(set)，并返回该位置原来的值。这一整套使用单指令(原子执行)。<br><code>while(test_and_set(&amp;lock) == 1)</code>可作为简单的<code>lock()</code>函数。当返回值为0时，则已获得锁，退出循环，否则继续忙等(spin lock)。<br><figure class="highlight cpp"><table><tr><td class="code"><pre><span class="line"><span class="comment">//pseudo-code</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> LOCKED   1</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> UNLOCKED 0</span></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">test_and_set</span><span class="params">(<span class="keyword">int</span>&amp; lock)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">int</span> initial = lock;</span><br><span class="line">    lock = LOCKED;</span><br><span class="line">    <span class="keyword">return</span> initial;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//used as a spin lock</span></span><br><span class="line"><span class="keyword">volatile</span> <span class="keyword">int</span> lock = <span class="number">0</span>;</span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">critical</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">while</span>(test_and_set(&amp;lock) == LOCKED);</span><br><span class="line">    <span class="comment">//[critical section]</span></span><br><span class="line">    lock = UNLOCKED;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<h3 id="test-and-test-and-set"><a href="#test-and-test-and-set" class="headerlink" title="test and test-and-set"></a>test and test-and-set</h3><p><em>在系统编程常用，应在高层的并发编程中避免，容易引发double-checked locking</em><br><code>test_and_set</code>可能会导致忙锁的资源竞争(总线锁，频繁的原子访问内存导致的cache失效)，为了降低overhead使用<code>test and test-and-set</code>。<br><figure class="highlight cpp"><table><tr><td class="code"><pre><span class="line"><span class="comment">// Entry Protocol</span></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">EnterCritical</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">do</span> &#123;</span><br><span class="line">        <span class="keyword">while</span>(locked == <span class="literal">true</span>);</span><br><span class="line">    &#125; <span class="keyword">while</span>(test_and_set(locked) == <span class="literal">true</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//if has short-circuit evaluation feature</span></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">EnterCritical</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">while</span>(locked == <span class="literal">true</span> || test_and_set(locked) == <span class="literal">true</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// Exit Protocol</span></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">ExitCritical</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    locked = <span class="literal">false</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<h3 id="fetch-and-add"><a href="#fetch-and-add" class="headerlink" title="fetch-and-add"></a>fetch-and-add</h3><p>FAA是原子操作，原子地在一个内存位置并加上一个值，并返回旧值。可以用于实现信号量和互斥锁。C++11有<code>std::atomic&lt;T&gt;::fetch_add</code>。<br><figure class="highlight cpp"><table><tr><td class="code"><pre><span class="line"><span class="comment">//x86 implementation</span></span><br><span class="line"><span class="comment">//C in GCC</span></span><br><span class="line"><span class="function"><span class="keyword">static</span> <span class="keyword">inline</span> <span class="keyword">int</span> <span class="title">fetch_and_add</span><span class="params">(<span class="keyword">int</span>* variable, <span class="keyword">int</span> value)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    __<span class="function">asm__ <span class="title">volatile</span><span class="params">(<span class="string">"lock; xaddl %0, %1"</span></span></span></span><br><span class="line">        : "+r"(value), "+m"(*variable) // input + output</span><br><span class="line">        : <span class="comment">// no input-only</span></span><br><span class="line">        : <span class="string">"memory"</span></span><br><span class="line">    );</span><br><span class="line">    <span class="keyword">return</span> value;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<h3 id="load-link-store-conditional-LL-SC"><a href="#load-link-store-conditional-LL-SC" class="headerlink" title="load-link/store-conditional (LL/SC)"></a>load-link/store-conditional (LL/SC)</h3><p>也叫load-reserved/store-conditional(LR/SC)。LL和SC是多线程同步的一对指令。load-link返回一个内存位置的现有值，store-conditional只在LL之后该位置没有修改的情况下写入新值。LL/SC是指令集实现的。</p>
<h3 id="compare-and-swap"><a href="#compare-and-swap" class="headerlink" title="compare-and-swap"></a>compare-and-swap</h3><p>CAS指令，只在一个内存位置与指定值相同的情况下写入新值（原子执行），返回比较的结果（bool）。<br><figure class="highlight cpp"><table><tr><td class="code"><pre><span class="line"><span class="comment">// pesudo-code</span></span><br><span class="line"><span class="function"><span class="keyword">bool</span> <span class="title">cas</span> <span class="params">(<span class="keyword">int</span>* p, <span class="keyword">int</span> oldVal, <span class="keyword">int</span> newVal)</span> <span class="comment">// atomic</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(*p != oldVal)</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">    *p = newVal;</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// example : atomic adder</span></span><br><span class="line"><span class="comment">// return the final value stored(not actual value)</span></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">add</span> <span class="params">(<span class="keyword">int</span>* p, <span class="keyword">int</span> a)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">bool</span> done = <span class="literal">false</span>;</span><br><span class="line">    <span class="keyword">while</span>(!done)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">int</span> value = *p; <span class="comment">// dont have to be atomic</span></span><br><span class="line">        done = cas(p, value, value + a);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> value + a;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<h2 id="C-11-multithreading"><a href="#C-11-multithreading" class="headerlink" title="C++11 multithreading"></a>C++11 multithreading</h2><h3 id="future"><a href="#future" class="headerlink" title="future"></a>future</h3><p>提供访问异步操作结果的机制。<strong>not copyable</strong></p>
<ul>
<li>使用(由<code>async</code>,<code>packaged_task</code>,<code>promise</code>创建的)异步操作可以提供一个<code>future</code></li>
<li>异步操作的创建者可以<code>valid()</code>，<code>wait()</code>或者<code>get()</code>，如果异步操作还没有提供值就会阻塞</li>
<li>当异步操作在准备好返回值给创建者的时候，可以使用与创建者的<code>future</code>关联的<code>promise::set_value</code></li>
</ul>
<figure class="highlight cpp"><table><tr><td class="code"><pre><span class="line">future.get() <span class="comment">//等待异步执行结束获取返回结果，只能调用一次</span></span><br><span class="line">future.wait() <span class="comment">//等待异步执行完成，无返回值。</span></span><br><span class="line">future.wait_for()</span><br><span class="line">future.wait_until()<span class="comment">//超时等待返回结果，返回std::future_status状态</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">enum</span> <span class="class"><span class="keyword">class</span> <span class="title">future_status</span> </span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line">    ready,</span><br><span class="line">    timeout,</span><br><span class="line">    deferred <span class="comment">//contains deferred function</span></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>
<h3 id="async"><a href="#async" class="headerlink" title="async"></a>async</h3><p>异步运行一个可调用对象<code>f</code>，返回<code>future</code>。<code>launch</code>可以指定是此线程lazy或者新线程异步。<br><figure class="highlight cpp"><table><tr><td class="code"><pre><span class="line"><span class="comment">// future from an async()</span></span><br><span class="line"><span class="built_in">std</span>::future&lt;<span class="keyword">int</span>&gt; f2 = <span class="built_in">std</span>::async(<span class="built_in">std</span>::launch::async, [] &#123; <span class="keyword">return</span> <span class="number">8</span>; &#125;);</span><br><span class="line"></span><br><span class="line"><span class="keyword">enum</span> <span class="class"><span class="keyword">class</span> <span class="title">launch</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line">    async, <span class="comment">//execute in new thread</span></span><br><span class="line">    deferred, <span class="comment">//(lazy evaluation) in the calling thread </span></span><br><span class="line">    <span class="comment">/* implementation-defined */</span></span><br><span class="line">    <span class="comment">//default ： async | deferred</span></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure></p>
<h3 id="packaged-task"><a href="#packaged-task" class="headerlink" title="packaged_task"></a>packaged_task</h3><p>提供<strong>可以</strong>被异步invoke的可调用对象Callable(function, lambda expression, bind expression, or another function object)的包装。返回<code>future</code>(值或异常)<code>packaged_task.get_future()</code>。<strong>not copyable</strong><br><figure class="highlight"><table><tr><td class="code"><pre><span class="line"><span class="comment">// future from a packaged_task</span></span><br><span class="line"><span class="built_in">std</span>::packaged_task&lt;<span class="keyword">int</span>()&gt; task([] &#123; <span class="keyword">return</span> <span class="number">7</span>; &#125;); <span class="comment">// wrap the function</span></span><br><span class="line"><span class="built_in">std</span>::future&lt;<span class="keyword">int</span>&gt; f1 = task.get_future();  <span class="comment">// get a future</span></span><br><span class="line">std::thread t(std::move(task)); // launch on a thread</span><br></pre></td></tr></table></figure></p>
<h3 id="promise"><a href="#promise" class="headerlink" title="promise"></a>promise</h3><p><code>promise</code> 是promise-future通信的推进端，设置<code>promise</code>状态与获取<code>future</code>状态同步。<strong>not copyable</strong><br><figure class="highlight cpp"><table><tr><td class="code"><pre><span class="line"><span class="comment">// future from a promise</span></span><br><span class="line"><span class="built_in">std</span>::promise&lt;<span class="keyword">int</span>&gt; p;</span><br><span class="line"><span class="built_in">std</span>::future&lt;<span class="keyword">int</span>&gt; f3 = p.get_future();</span><br><span class="line"><span class="built_in">std</span>::thread([&amp;p] &#123; p.set_value_at_thread_exit(<span class="number">9</span>); &#125;).detach();</span><br></pre></td></tr></table></figure></p>
<h3 id="condition-variable"><a href="#condition-variable" class="headerlink" title="condition_variable"></a>condition_variable</h3><p>同步原语，用于阻塞一个或多个线程，直到另一个线程修改共享变量(the condition)，并<code>notify</code>(condition_variable)。<br><strong>not copyable, not movable</strong></p>
<h4 id="线程修改变量"><a href="#线程修改变量" class="headerlink" title="线程修改变量"></a>线程修改变量</h4><ul>
<li>获得<code>mutex</code>(一般通过<code>lock_guard</code>)</li>
<li>在获得锁期间做修改</li>
<li><code>notify_one()</code>或<code>notify_all()</code>(无需在获得锁期间)</li>
</ul>
<p>即使共享变量是<code>atomic</code>的，也必须在获得<code>mutex</code>的情况下修改，来保证等待线程能获得正确结果</p>
<h4 id="线程等待变量"><a href="#线程等待变量" class="headerlink" title="线程等待变量"></a>线程等待变量</h4><ul>
<li>获得<code>unique_lock&lt;mutex&gt;</code></li>
<li>检查共享变量(the condition)，防止已经被修改并且<code>notify</code></li>
<li><code>wait()</code>,<code>wait_for()</code>或<code>wait_until()</code>，原子地释放锁，并暂停线程执行。</li>
<li>当<code>condition_variable</code> <code>notify</code>后，原子地获得<code>mutex</code></li>
</ul>
<p><code>condition_variable</code>只与<code>unique_lock&lt;mutex&gt;</code>配合(效率最大化)。<code>condition_variable_any</code>可与其他锁对象配合。<br><figure class="highlight cpp"><table><tr><td class="code"><pre><span class="line">condition_variable.wait(unique_lock&lt;mutex&gt;&amp; lock)</span><br><span class="line"><span class="comment">//unlock mutex, block thread, wait for notify</span></span><br><span class="line">condition_variable.wait(unique_lock&lt;mutex&gt;&amp; lock, Predicate pred)</span><br><span class="line"><span class="comment">//while (!pred()) wait(lock);</span></span><br></pre></td></tr></table></figure></p>
<h2 id="LLVM-ThreadPool"><a href="#LLVM-ThreadPool" class="headerlink" title="LLVM ThreadPool"></a>LLVM ThreadPool</h2><p>llvm里的一个简单的线程池，异步并行地执行一定数量的线程。<code>async</code>用来向池中添加任务。使用了两个<code>condition_variable</code>，一个用来控制任务序列的访问，一个用来标记任务队列全部完成。<br><figure class="highlight cpp"><table><tr><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">ThreadPool</span> &#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">  <span class="keyword">using</span> TaskTy = <span class="built_in">std</span>::function&lt;<span class="keyword">void</span>()&gt;;</span><br><span class="line">  <span class="keyword">using</span> PackagedTaskTy = <span class="built_in">std</span>::packaged_task&lt;<span class="keyword">void</span>()&gt;;</span><br><span class="line"></span><br><span class="line">  <span class="comment">/// Construct a pool using the hardware strategy \p S for mapping hardware</span></span><br><span class="line">  <span class="comment">/// execution resources (threads, cores, CPUs)</span></span><br><span class="line">  <span class="comment">/// Defaults to using the maximum execution resources in the system, but</span></span><br><span class="line">  <span class="comment">/// accounting for the affinity mask.</span></span><br><span class="line">  ThreadPool(ThreadPoolStrategy S = hardware_concurrency());</span><br><span class="line"></span><br><span class="line">  <span class="comment">/// Blocking destructor: the pool will wait for all the threads to complete.</span></span><br><span class="line">  ~ThreadPool();</span><br><span class="line"></span><br><span class="line">  <span class="comment">/// Asynchronous submission of a task to the pool. The returned future can be</span></span><br><span class="line">  <span class="comment">/// used to wait for the task to finish and is *non-blocking* on destruction.</span></span><br><span class="line">  <span class="keyword">template</span> &lt;<span class="keyword">typename</span> Function, <span class="keyword">typename</span>... Args&gt;</span><br><span class="line">  <span class="keyword">inline</span> <span class="built_in">std</span>::shared_future&lt;<span class="keyword">void</span>&gt; async(Function &amp;&amp;F, Args &amp;&amp;... ArgList) &#123;</span><br><span class="line">    <span class="keyword">auto</span> Task =</span><br><span class="line">        <span class="built_in">std</span>::bind(<span class="built_in">std</span>::forward&lt;Function&gt;(F), <span class="built_in">std</span>::forward&lt;Args&gt;(ArgList)...);</span><br><span class="line">    <span class="keyword">return</span> asyncImpl(<span class="built_in">std</span>::move(Task));</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="comment">/// Asynchronous submission of a task to the pool. The returned future can be</span></span><br><span class="line">  <span class="comment">/// used to wait for the task to finish and is *non-blocking* on destruction.</span></span><br><span class="line">  <span class="keyword">template</span> &lt;<span class="keyword">typename</span> Function&gt;</span><br><span class="line">  <span class="keyword">inline</span> <span class="built_in">std</span>::shared_future&lt;<span class="keyword">void</span>&gt; async(Function &amp;&amp;F) &#123;</span><br><span class="line">    <span class="keyword">return</span> asyncImpl(<span class="built_in">std</span>::forward&lt;Function&gt;(F));</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="comment">/// Blocking wait for all the threads to complete and the queue to be empty.</span></span><br><span class="line">  <span class="comment">/// It is an error to try to add new tasks while blocking on this call.</span></span><br><span class="line">  <span class="function"><span class="keyword">void</span> <span class="title">wait</span><span class="params">()</span></span>;</span><br><span class="line"></span><br><span class="line">  <span class="function"><span class="keyword">unsigned</span> <span class="title">getThreadCount</span><span class="params">()</span> <span class="keyword">const</span> </span>&#123; <span class="keyword">return</span> ThreadCount; &#125;</span><br><span class="line"></span><br><span class="line">  <span class="comment">/// Returns true if the current thread is a worker thread of this thread pool.</span></span><br><span class="line">  <span class="function"><span class="keyword">bool</span> <span class="title">isWorkerThread</span><span class="params">()</span> <span class="keyword">const</span></span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">  <span class="function"><span class="keyword">bool</span> <span class="title">workCompletedUnlocked</span><span class="params">()</span> </span>&#123; <span class="keyword">return</span> !ActiveThreads &amp;&amp; Tasks.empty(); &#125;</span><br><span class="line"></span><br><span class="line">  <span class="comment">/// Asynchronous submission of a task to the pool. The returned future can be</span></span><br><span class="line">  <span class="comment">/// used to wait for the task to finish and is *non-blocking* on destruction.</span></span><br><span class="line">  <span class="built_in">std</span>::shared_future&lt;<span class="keyword">void</span>&gt; asyncImpl(TaskTy F);</span><br><span class="line"></span><br><span class="line">  <span class="comment">/// Threads in flight</span></span><br><span class="line">  <span class="built_in">std</span>::<span class="built_in">vector</span>&lt;llvm::thread&gt; Threads;</span><br><span class="line"></span><br><span class="line">  <span class="comment">/// Tasks waiting for execution in the pool.</span></span><br><span class="line">  <span class="built_in">std</span>::<span class="built_in">queue</span>&lt;PackagedTaskTy&gt; Tasks;</span><br><span class="line"></span><br><span class="line">  <span class="comment">/// Locking and signaling for accessing the Tasks queue.</span></span><br><span class="line">  <span class="built_in">std</span>::mutex QueueLock;</span><br><span class="line">  <span class="built_in">std</span>::condition_variable QueueCondition;</span><br><span class="line"></span><br><span class="line">  <span class="comment">/// Signaling for job completion</span></span><br><span class="line">  <span class="built_in">std</span>::condition_variable CompletionCondition;</span><br><span class="line"></span><br><span class="line">  <span class="comment">/// Keep track of the number of thread actually busy</span></span><br><span class="line">  <span class="keyword">unsigned</span> ActiveThreads = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">if</span> LLVM_ENABLE_THREADS <span class="comment">// avoids warning for unused variable</span></span></span><br><span class="line">  <span class="comment">/// Signal for the destruction of the pool, asking thread to exit.</span></span><br><span class="line">  <span class="keyword">bool</span> EnableFlag = <span class="literal">true</span>;</span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br><span class="line"></span><br><span class="line">  <span class="keyword">unsigned</span> ThreadCount;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure></p>
<p>具体的实现区分了是否使用多线程，如果开启了多线程，则用<code>vector</code>里的线程不断的找任务队列里的任务执行。</p>
<ul>
<li>加入任务时，<code>QueueCondition.notify_one()</code>唤醒一个正在等待任务的线程</li>
<li>工作线程内，在任务队列不空的时候，不断取任务执行。注意一下工作线程执行完任务后，都要减少<code>ActiveThreads</code>，并判断自己是不是最后一个Active的线程以及任务队列是否已空，如果是，那么发出<code>CompletionCondition.notify_all()</code>提醒线程池的<code>ThreadPool::wait()</code></li>
<li><code>wait()</code>用于等待任务队列清空(但并不销毁线程池)，清空后的线程池里工作线程会阻塞在<br><code>QueueCondition.wait(LockGuard, [&amp;] { return !EnableFlag || !Tasks.empty(); });</code></li>
<li>线程池析构时，先将<code>EnableFlag</code>置false，然后使用<code>QueueCondition.notify_all()</code>唤醒所有还在等待任务的线程，接着等待工作线程把任务队列清空后销毁线程(<code>join()</code>)。</li>
</ul>
<figure class="highlight cpp"><table><tr><td class="code"><pre><span class="line">ThreadPool::ThreadPool(ThreadPoolStrategy S)</span><br><span class="line">    : ThreadCount(S.compute_thread_count()) &#123;</span><br><span class="line">  <span class="comment">// Create ThreadCount threads that will loop forever, wait on QueueCondition</span></span><br><span class="line">  <span class="comment">// for tasks to be queued or the Pool to be destroyed.</span></span><br><span class="line">  Threads.reserve(ThreadCount);</span><br><span class="line">  <span class="keyword">for</span> (<span class="keyword">unsigned</span> ThreadID = <span class="number">0</span>; ThreadID &lt; ThreadCount; ++ThreadID) &#123;</span><br><span class="line">    Threads.emplace_back([S, ThreadID, <span class="keyword">this</span>] &#123;</span><br><span class="line">      S.apply_thread_strategy(ThreadID);</span><br><span class="line">      <span class="keyword">while</span> (<span class="literal">true</span>) &#123;</span><br><span class="line">        PackagedTaskTy Task;</span><br><span class="line">        &#123;</span><br><span class="line">          <span class="built_in">std</span>::unique_lock&lt;<span class="built_in">std</span>::mutex&gt; LockGuard(QueueLock);</span><br><span class="line">          <span class="comment">// Wait for tasks to be pushed in the queue</span></span><br><span class="line">          QueueCondition.wait(LockGuard,</span><br><span class="line">                              [&amp;] &#123; <span class="keyword">return</span> !EnableFlag || !Tasks.empty(); &#125;);</span><br><span class="line">          <span class="comment">// Exit condition</span></span><br><span class="line">          <span class="keyword">if</span> (!EnableFlag &amp;&amp; Tasks.empty())</span><br><span class="line">            <span class="keyword">return</span>;</span><br><span class="line">          <span class="comment">// Yeah, we have a task, grab it and release the lock on the queue</span></span><br><span class="line"></span><br><span class="line">          <span class="comment">// We first need to signal that we are active before popping the queue</span></span><br><span class="line">          <span class="comment">// in order for wait() to properly detect that even if the queue is</span></span><br><span class="line">          <span class="comment">// empty, there is still a task in flight.</span></span><br><span class="line">          ++ActiveThreads;</span><br><span class="line">          Task = <span class="built_in">std</span>::move(Tasks.front());</span><br><span class="line">          Tasks.pop();</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// Run the task we just grabbed</span></span><br><span class="line">        Task();</span><br><span class="line"></span><br><span class="line">        <span class="keyword">bool</span> Notify;</span><br><span class="line">        &#123;</span><br><span class="line">          <span class="comment">// Adjust `ActiveThreads`, in case someone waits on ThreadPool::wait()</span></span><br><span class="line">          <span class="built_in">std</span>::lock_guard&lt;<span class="built_in">std</span>::mutex&gt; LockGuard(QueueLock);</span><br><span class="line">          --ActiveThreads;</span><br><span class="line">          Notify = workCompletedUnlocked();</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// Notify task completion if this is the last active thread, in case</span></span><br><span class="line">        <span class="comment">// someone waits on ThreadPool::wait().</span></span><br><span class="line">        <span class="keyword">if</span> (Notify)</span><br><span class="line">          CompletionCondition.notify_all();</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">void</span> ThreadPool::wait() &#123;</span><br><span class="line">  <span class="comment">// Wait for all threads to complete and the queue to be empty</span></span><br><span class="line">  <span class="built_in">std</span>::unique_lock&lt;<span class="built_in">std</span>::mutex&gt; LockGuard(QueueLock);</span><br><span class="line">  CompletionCondition.wait(LockGuard, [&amp;] &#123; <span class="keyword">return</span> workCompletedUnlocked(); &#125;);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">bool</span> ThreadPool::isWorkerThread() <span class="keyword">const</span> &#123;</span><br><span class="line">  llvm::thread::id CurrentThreadId = llvm::this_thread::get_id();</span><br><span class="line">  <span class="keyword">for</span> (<span class="keyword">const</span> llvm::thread &amp;Thread : Threads)</span><br><span class="line">    <span class="keyword">if</span> (CurrentThreadId == Thread.get_id())</span><br><span class="line">      <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">  <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="built_in">std</span>::shared_future&lt;<span class="keyword">void</span>&gt; ThreadPool::asyncImpl(TaskTy Task) &#123;</span><br><span class="line">  <span class="comment">/// Wrap the Task in a packaged_task to return a future object.</span></span><br><span class="line">  PackagedTaskTy PackagedTask(std::move(Task));</span><br><span class="line">  <span class="keyword">auto</span> Future = PackagedTask.get_future();</span><br><span class="line">  &#123;</span><br><span class="line">    <span class="comment">// Lock the queue and push the new task</span></span><br><span class="line">    <span class="built_in">std</span>::unique_lock&lt;<span class="built_in">std</span>::mutex&gt; LockGuard(QueueLock);</span><br><span class="line"></span><br><span class="line">    <span class="comment">// Don't allow enqueueing after disabling the pool</span></span><br><span class="line">    assert(EnableFlag &amp;&amp; <span class="string">"Queuing a thread during ThreadPool destruction"</span>);</span><br><span class="line"></span><br><span class="line">    Tasks.push(<span class="built_in">std</span>::move(PackagedTask));</span><br><span class="line">  &#125;</span><br><span class="line">  QueueCondition.notify_one();</span><br><span class="line">  <span class="keyword">return</span> Future.share();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// The destructor joins all threads, waiting for completion.</span></span><br><span class="line">ThreadPool::~ThreadPool() &#123;</span><br><span class="line">  &#123;</span><br><span class="line">    <span class="built_in">std</span>::unique_lock&lt;<span class="built_in">std</span>::mutex&gt; LockGuard(QueueLock);</span><br><span class="line">    EnableFlag = <span class="literal">false</span>;</span><br><span class="line">  &#125;</span><br><span class="line">  QueueCondition.notify_all();</span><br><span class="line">  <span class="keyword">for</span> (<span class="keyword">auto</span> &amp;Worker : Threads)</span><br><span class="line">    Worker.join();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>如果是单线程，就只用<code>launch::deferred</code>的<code>async</code>在本线程里lazy evaluation。为了和多线程统一，就用<code>package_task</code>包装<code>future.get()</code>后加入任务队列。<br><figure class="highlight cpp"><table><tr><td class="code"><pre><span class="line"><span class="comment">// No threads are launched, issue a warning if ThreadCount is not 0</span></span><br><span class="line">ThreadPool::ThreadPool(ThreadPoolStrategy S)</span><br><span class="line">    : ThreadCount(S.compute_thread_count()) &#123;</span><br><span class="line">  <span class="keyword">if</span> (ThreadCount != <span class="number">1</span>) &#123;</span><br><span class="line">    errs() &lt;&lt; <span class="string">"Warning: request a ThreadPool with "</span> &lt;&lt; ThreadCount</span><br><span class="line">           &lt;&lt; <span class="string">" threads, but LLVM_ENABLE_THREADS has been turned off\n"</span>;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">void</span> ThreadPool::wait() &#123;</span><br><span class="line">  <span class="comment">// Sequential implementation running the tasks</span></span><br><span class="line">  <span class="keyword">while</span> (!Tasks.empty()) &#123;</span><br><span class="line">    <span class="keyword">auto</span> Task = <span class="built_in">std</span>::move(Tasks.front());</span><br><span class="line">    Tasks.pop();</span><br><span class="line">    Task();</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="built_in">std</span>::shared_future&lt;<span class="keyword">void</span>&gt; ThreadPool::asyncImpl(TaskTy Task) &#123;</span><br><span class="line">  <span class="comment">// Get a Future with launch::deferred execution using std::async</span></span><br><span class="line">  <span class="keyword">auto</span> Future = <span class="built_in">std</span>::async(<span class="built_in">std</span>::launch::deferred, <span class="built_in">std</span>::move(Task)).share();</span><br><span class="line">  <span class="comment">// Wrap the future so that both ThreadPool::wait() can operate and the</span></span><br><span class="line">  <span class="comment">// returned future can be sync'ed on.</span></span><br><span class="line">  <span class="function">PackagedTaskTy <span class="title">PackagedTask</span><span class="params">([Future]()</span> </span>&#123; Future.get(); &#125;);</span><br><span class="line">  Tasks.push(<span class="built_in">std</span>::move(PackagedTask));</span><br><span class="line">  <span class="keyword">return</span> Future;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">ThreadPool::~ThreadPool() &#123; wait(); &#125;</span><br></pre></td></tr></table></figure></p>

      
    </div>
    
    
    

    

    

    

    <footer class="post-footer">
      
        <div class="post-tags">
          
            <a href="/tags/multithreading/" rel="tag"># multithreading</a>
          
        </div>
      

      
      
      

      
        <div class="post-nav">
          <div class="post-nav-next post-nav-item">
            
              <a href="/2021/03/30/Inequalities/" rel="next" title="Inequalities">
                <i class="fa fa-chevron-left"></i> Inequalities
              </a>
            
          </div>

          <span class="post-nav-divider"></span>

          <div class="post-nav-prev post-nav-item">
            
              <a href="/2021/05/25/Template-index-sequence-parameter-pack-fold-expression/" rel="prev" title="[Template] index_sequence, parameter pack, fold expression">
                [Template] index_sequence, parameter pack, fold expression <i class="fa fa-chevron-right"></i>
              </a>
            
          </div>
        </div>
      

      
      
    </footer>
  </div>
  
  
  
  </article>



    <div class="post-spread">
      
    </div>
  </div>


          </div>
          


          

  



        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    
      <div id="sidebar-dimmer"></div>
    
    <div class="sidebar-inner">

      

      
        <ul class="sidebar-nav motion-element">
          <li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap">
            文章目录
          </li>
          <li class="sidebar-nav-overview" data-target="site-overview-wrap">
            站点概览
          </li>
        </ul>
      

      <section class="site-overview-wrap sidebar-panel">
        <div class="site-overview">
          <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
            
              <img class="site-author-image" itemprop="image" src="/images/MOB.jpg" alt="HTelepathH">
            
              <p class="site-author-name" itemprop="name">HTelepathH</p>
              <p class="site-description motion-element" itemprop="description">Learning by doing.</p>
          </div>

          <nav class="site-state motion-element">

            
              <div class="site-state-item site-state-posts">
              
                <a href="/archives">
              
                  <span class="site-state-item-count">25</span>
                  <span class="site-state-item-name">日志</span>
                </a>
              </div>
            

            
              
              
              <div class="site-state-item site-state-categories">
                <a href="/categories/index.html">
                  <span class="site-state-item-count">12</span>
                  <span class="site-state-item-name">分类</span>
                </a>
              </div>
            

            
              
              
              <div class="site-state-item site-state-tags">
                <a href="/tags/index.html">
                  <span class="site-state-item-count">15</span>
                  <span class="site-state-item-name">标签</span>
                </a>
              </div>
            

          </nav>

          

          
            <div class="links-of-author motion-element">
                
                  <span class="links-of-author-item">
                    <a href="99088577@qq.com" target="_blank" title="Mail">
                      Mail</a>
                  </span>
                
                  <span class="links-of-author-item">
                    <a href="https://gitee.com/htelepathh" target="_blank" title="Gitee">
                      Gitee</a>
                  </span>
                
                  <span class="links-of-author-item">
                    <a href="https://github.com/htlpt" target="_blank" title="GitHub">
                      GitHub</a>
                  </span>
                
                  <span class="links-of-author-item">
                    <a href="https://weibo.com/u/6207125886" target="_blank" title="微博">
                      微博</a>
                  </span>
                
                  <span class="links-of-author-item">
                    <a href="https://www.zhihu.com/people/huang-he-tu" target="_blank" title="知乎">
                      知乎</a>
                  </span>
                
            </div>
          

          
          

          
          

          

        </div>
      </section>

      
      <!--noindex-->
        <section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">
          <div class="post-toc">

            
              
            

            
              <div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-2"><a class="nav-link" href="#Comcepts"><span class="nav-number">1.</span> <span class="nav-text">Comcepts</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#mutex"><span class="nav-number">1.1.</span> <span class="nav-text">mutex</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#critical-section"><span class="nav-number">1.2.</span> <span class="nav-text">critical section</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#semaphore"><span class="nav-number">1.3.</span> <span class="nav-text">semaphore</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#生产者消费者问题"><span class="nav-number">1.3.1.</span> <span class="nav-text">生产者消费者问题</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#non-blocking-lock-free-wait-free"><span class="nav-number">1.4.</span> <span class="nav-text">non-blocking, lock-free,  wait-free</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Implementation"><span class="nav-number">2.</span> <span class="nav-text">Implementation</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#test-and-set"><span class="nav-number">2.1.</span> <span class="nav-text">test-and-set</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#test-and-test-and-set"><span class="nav-number">2.2.</span> <span class="nav-text">test and test-and-set</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#fetch-and-add"><span class="nav-number">2.3.</span> <span class="nav-text">fetch-and-add</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#load-link-store-conditional-LL-SC"><span class="nav-number">2.4.</span> <span class="nav-text">load-link/store-conditional (LL/SC)</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#compare-and-swap"><span class="nav-number">2.5.</span> <span class="nav-text">compare-and-swap</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#C-11-multithreading"><span class="nav-number">3.</span> <span class="nav-text">C++11 multithreading</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#future"><span class="nav-number">3.1.</span> <span class="nav-text">future</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#async"><span class="nav-number">3.2.</span> <span class="nav-text">async</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#packaged-task"><span class="nav-number">3.3.</span> <span class="nav-text">packaged_task</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#promise"><span class="nav-number">3.4.</span> <span class="nav-text">promise</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#condition-variable"><span class="nav-number">3.5.</span> <span class="nav-text">condition_variable</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#线程修改变量"><span class="nav-number">3.5.1.</span> <span class="nav-text">线程修改变量</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#线程等待变量"><span class="nav-number">3.5.2.</span> <span class="nav-text">线程等待变量</span></a></li></ol></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#LLVM-ThreadPool"><span class="nav-number">4.</span> <span class="nav-text">LLVM ThreadPool</span></a></li></ol></div>
            

          </div>
        </section>
      <!--/noindex-->
      

      

    </div>
  </aside>


        
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright">&copy; <span itemprop="copyrightYear">2022</span>
  <span class="with-love">
    <i class="fa fa-angle-double-left"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">HTelepathH</span>

  
</div>




        







        
      </div>
    </footer>

    
      <div class="back-to-top">
        <i class="fa fa-arrow-up"></i>
        
      </div>
    

    

  </div>

  

<script type="text/javascript">
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>









  












  
  
    <script type="text/javascript" src="/lib/jquery/index.js?v=2.1.3"></script>
  

  
  
    <script type="text/javascript" src="/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script>
  

  
  
    <script type="text/javascript" src="/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script>
  

  
  
    <script type="text/javascript" src="/lib/velocity/velocity.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script>
  


  


  <script type="text/javascript" src="/js/src/utils.js?v=5.1.4"></script>

  <script type="text/javascript" src="/js/src/motion.js?v=5.1.4"></script>



  
  

  
  <script type="text/javascript" src="/js/src/scrollspy.js?v=5.1.4"></script>
<script type="text/javascript" src="/js/src/post-details.js?v=5.1.4"></script>



  


  <script type="text/javascript" src="/js/src/bootstrap.js?v=5.1.4"></script>



  


  




	





  





  












  





  

  

  

  
  

  
  


  

  

</body>
</html>
